package lrscp.lib.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ArrayBlockingQueue;

public class MathUtils {
    private static interface ChooseListener {
        void onChoose(int[] result);
    }

    /**
     * iterate: choose different number of combination from total such as
     * Chooser(4,1) means choose 1 number from [0,1,2,3] Chooser(4,2) meas
     * choose 2 numbers from [0,1,2,3] the result will be different combination
     * of numbers.
     */
    public static class Chooser {
        ArrayBlockingQueue<int[]> q = new ArrayBlockingQueue<int[]>(100);

        public Chooser(final int total, final int num) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (total > 0 && num > 0 && total >= num)
                        choose(total, num, 0, 0, new int[num], lsnr);
                    try {
                        q.put(new int[0]);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        private static void choose(int total, int num, int start, int level, int[] result,
                ChooseListener lsnr) {
            // int max = start + total - num + 1;
            int max = total - num;
            // Log.i(" level:" + level + " start:" + start + " num:" + num +
            // " max:" + max);
            for (int i = start; i <= max; i++) {
                result[level] = i;
                if (num == 1) {
                    if (lsnr != null)
                        lsnr.onChoose(result);
                } else
                    choose(total, num - 1, i + 1, level + 1, result, lsnr);
            }
        }

        ChooseListener lsnr = new ChooseListener() {
            @Override
            public void onChoose(int[] result) {
                try {
                    q.put(Arrays.copyOf(result, result.length));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        public int[] next() {
            try {
                int[] r = q.take();
                return r.length == 0 ? null : r;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    /**
     * 
     * @param num
     * @return null if NumberFormatException
     */
    public static Long valueOfLong(String num) {
        Long cnt = null;
        try {
            cnt = Long.valueOf(num);
        } catch (NumberFormatException e) {}
        return cnt;
    }

    /**
     * 
     * @param num
     * @return null if NumberFormatException
     */
    public static Long valueOfLong(String num, long defaultValue) {
        Long cnt = defaultValue;
        try {
            cnt = Long.valueOf(num);
        } catch (NumberFormatException e) {}
        return cnt;
    }

    /**
     * 
     * @param num
     * @return null if NumberFormatException
     */
    public static Integer valueOfInteger(String num) {
        Integer cnt = null;
        try {
            cnt = Integer.valueOf(num);
        } catch (NumberFormatException e) {}
        return cnt;
    }

    /**
     * 
     * @param num
     * @return null if NumberFormatException
     */
    public static Integer valueOfInteger(String num, int defaultValue) {
        Integer cnt = defaultValue;
        try {
            cnt = Integer.valueOf(num);
        } catch (NumberFormatException e) {}
        return cnt;
    }

    /**
     * 
     * @param num
     * @return null if NumberFormatException
     */
    public static Float valueOfFloat(String num) {
        Float cnt = null;
        try {
            cnt = Float.valueOf(num);
        } catch (NumberFormatException e) {}
        return cnt;
    }

    /**
     * 
     * @param num
     * @return null if NumberFormatException
     */
    public static Float valueOfFloat(String num, float defaultValue) {
        Float cnt = defaultValue;
        try {
            cnt = Float.valueOf(num);
        } catch (NumberFormatException e) {}
        return cnt;
    }

    public static Integer[] range(int from, int to, int step) {
        if (step < 1)
            return null;
        ArrayList<Integer> res = new ArrayList<Integer>();
        if (from > to) {
            while (from >= to) {
                res.add(from);
                from -= step;
            }
        } else {
            while (from <= to) {
                res.add(from);
                from += step;
            }
        }
        return res.toArray(new Integer[res.size()]);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

    }

}
